package org.example.uua.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;

/**
 * @author : yurui
 * @date : 2024/6/1
 * @TIME : 18:23
 * @project : AuthDemo
 * 授权认证服务的三个核心配置
 */

@Configuration
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    private final AuthorizationCodeServices authorizationCodeServices;
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private final TokenStore tokenStore;
    private final ClientDetailsService clientDetailsService;
    private static final String RESOURCE_ID = "salary"; //资源ID


    public MyAuthorizationConfig(AuthorizationCodeServices authorizationCodeServices,
                                 AuthenticationManager authenticationManager,
                                 UserDetailsService userDetailsService,
                                 TokenStore tokenStore,
                                 ClientDetailsService clientDetailsService) {
        this.authorizationCodeServices = authorizationCodeServices;
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.tokenStore = tokenStore;
        this.clientDetailsService = clientDetailsService;
    }

    //用来配置令牌端点的安全约束
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()")  //  oauth/token_key 公开
                .checkTokenAccess("permitAll")  // oauth/check_token 公开
                .allowFormAuthenticationForClients(); // 表单认证，申请令牌
    }

    //用来配置客户端详细信息服务，
    //客户端详细信息在这里进行初始化，你能够把客户端详细信息写死在这里或者通关数据库来存储调取详细信息
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        //内存方式配置用户信息
        //clientId: 用来标识客户的ID，必须
        //secret: 客户端安全码，如果有的话。在微信登录中就是必须
        //scope: 用来限制客户端的访问范围，如果是空（默认）的话，
        //       那么客户端拥有全部的访问范围
        //authorizedGrantTypes：此客户端可以使用的授权类型，默认为空
        //authorities: 此客户端可以使用的权限(基于Spring Security authorities)
        //redirectUris: 回调地址。授权服务会往该回调地址推送此客户端相关信息
        clients.inMemory()
                .withClient("c1")
                .secret(new BCryptPasswordEncoder().encode("yurui"))
                .resourceIds(RESOURCE_ID)
                .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
                .scopes("all")
                .authorities()
                .autoApprove(false)
                .redirectUris("http://www.baidu.com");

    }

    //用来配置令牌（token）的访问，端点和令牌服务（tokenServices）
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints.pathMapping("/oauth/confirm_access", "/customer/confirm_access")
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .tokenServices(tokenService())
                .allowedTokenEndpointRequestMethods(HttpMethod.POST)
                .authorizationCodeServices(authorizationCodeServices);
    }

    public AuthorizationServerTokenServices tokenService(){
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService);
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore);
        //令牌默认有效期2小时
        services.setAccessTokenValiditySeconds(7200);
        // 刷新令牌默认有效期3天
        services.setRefreshTokenValiditySeconds(259200);
        return services;
    }

}
